#pragma once
#ifndef __LIT__META__OBJECT__INCLUDED__HH__
#define __LIT__META__OBJECT__INCLUDED__HH__

#include <LitExceptions.h>
#include <LitMetaGroup.h>

namespace Lit
{
	class LIT_API MetaObject : public Named<true>
	{
	public:
		typedef std::unordered_map<String,MetaGroup> GroupMap;

	protected:
		GroupMap mProps;

	public:
		MetaObject( const String &name = "" );
		MetaObject( const MetaObject& rk );
		MetaObject& operator=( const MetaObject& rk );
		virtual ~MetaObject();
		
		void merge( const MetaGroup& rk, bool replace_old = true );
		void merge( const MetaObject& rk, bool replace_old = true );
		
		void clear(){ mProps.clear(); }
		bool empty() const{ return mProps.empty(); }
		size_t size() const{ return mProps.size(); }
		
		MetaGroup& operator[]( const String &name );

		GroupMap::iterator find( const String &key );
		GroupMap::const_iterator find( const String &key ) const;
		
		GroupMap::iterator begin();
		GroupMap::iterator end();

		GroupMap::const_iterator begin() const;
		GroupMap::const_iterator end() const;

		bool hasGroup( const String &name ) const;
		
		MetaGroup& getGroup( const String &name );
		const MetaGroup& getGroup( const String &name ) const;

		void setGroup( const MetaGroup& d );
		void setProperty( const String &group, const String &key, const String &val );

		template<typename T> 
		T getProperty( const String &group, const String &key, const T& def_val = T() ){
			if( !hasGroup(group) ) return def_val;
			if( !mProps[group].hasKey( key ) ) return def_val;
			return mProps[group].getProperty<T>( key, def_val );
		}
	};
	class LIT_API MetaGroupSerialiser: public XmlSerialiser<MetaGroup>
	{
	public:
		MetaGroupSerialiser();
		virtual ~MetaGroupSerialiser();
		
		void saveObject( TiXmlDocument * doc, const MetaGroup& in );
		void loadObject( TiXmlDocument * doc, const String &base_dir, MetaGroup& out );
		void saveObject( TiXmlElement * doc, const MetaGroup& in );
		void loadObject( TiXmlElement * doc, const String &base_dir, MetaGroup& out );
	};
	class LIT_API MetaObjectSerialiser: public XmlSerialiser<MetaObject>
	{
	protected:
		MetaObjectSerialiser(const String &override_name);
	public:
		MetaObjectSerialiser();
		virtual ~MetaObjectSerialiser();

		void saveObject( TiXmlDocument * doc, const MetaObject& in );
		void loadObject( TiXmlDocument * doc, const String &base_dir, MetaObject& out );
	};

};

#endif